using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Net.Http;
using System.Security.Claims;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Abp.Authorization;
using Abp.Authorization.Users;
using Abp.MultiTenancy;
using Abp.Runtime.Security;
using Abp.UI;
using Yozeev.Authentication.External;
using Yozeev.Authentication.JwtBearer;
using Yozeev.Authorization;
using Yozeev.Models.TokenAuth;
using Yozeev.MultiTenancy;
using Yozeev.UserManagerment.Users;
using Abp.Runtime.Caching;
using Yozeev.Authorization.Impersonation;
using Abp;
using Abp.Domain.Uow;
using Abp.IdentityFramework;
using Abp.Json;
using L._52ABP.Common.Consts;
using Yozeev.Authentication.External.ExternalAuth;
using Yozeev.Authentication.External.ExternalAuth.Dto;
using Yozeev.DataFileObjects;
using Yozeev.DataFileObjects.DataTempCache;
using Yozeev.Security.Captcha;
using Yozeev.UserManagerment.Users.UserLink;
using Abp.Extensions;
using L._52ABP.Common.Net.MimeTypes;
using L._52ABP.Core.VerificationCodeStore;
using Yozeev.BusinessLogic.DomainService;
using Yozeev.Models;
using Yozeev.BusinessLogic;
using Yozeev.EntityFrameworkCore;
using Yozeev.SystemConfig.BasicConfig.DomainService;
using Yozeev.BusinessLogic.Stats.Dtos;
using Abp.Domain.Entities.Auditing;
using DotNetCore.CAP;
using Abp.AutoMapper;
using Yozeev.Common;
using Newtonsoft.Json;
using Yozeev.Authorization.Roles;

namespace Yozeev.Controllers
{
    [Route("api/[controller]/[action]")]
    public class ActivityTempController : CommonController//YozeevControllerBase
    {
        private readonly ITenantCache _tenantCache;
        private readonly ICacheManager _cacheManager;
        private readonly IImpersonationManager _impersonationManager;
        private readonly IUserLinkManager _userLinkManager;
        private readonly IdentityOptions _identityOptions;
        private readonly IDataTempFileCacheManager _dataTempFileCacheManager;
        private readonly IDataFileObjectManager _dataFileObjectManager;
        private readonly ActivityTempManager _activityTempManager;
        private readonly ActivityManager _activityManager;
        //private readonly SourceManager _sourceManager;
        private readonly TicketDetailManager _ticketDetailManager;
        private readonly ICapPublisher _capBus;


        public ActivityTempController(
            ITenantCache tenantCache,
            ICacheManager cacheManager,
            IImpersonationManager impersonationManager,
            IUserLinkManager userLinkManager,
            IOptions<IdentityOptions> identityOptions,
            UserManager userManager, 
            IDataFileObjectManager dataFileObjectManager, 
            IDataTempFileCacheManager dataTempFileCacheManager
            , ActivityTempManager activityTempManager
            , SourceManager sourceManager
            , ScheduleManager scheduleManager
            , PayMethodManager payMethodManager
            , TicketPriceManager ticketPriceManager
            , CustomerManager customerManager
            , TicketDetailManager ticketDetailManager
            , ActivityManager activityManager
            , ICapPublisher capBus
            , TravelAgencyManager travelManager
            ) :base(sourceManager, scheduleManager, payMethodManager, cacheManager, ticketPriceManager, customerManager, userManager, travelManager)
        {
            _tenantCache = tenantCache;
            _cacheManager = cacheManager;
            _impersonationManager = impersonationManager;
            _userLinkManager = userLinkManager;
            _identityOptions = identityOptions.Value;
            _dataFileObjectManager = dataFileObjectManager;
            _dataTempFileCacheManager = dataTempFileCacheManager;
            _activityTempManager = activityTempManager;
            _ticketDetailManager = ticketDetailManager;
            _activityManager = activityManager;
            _capBus = capBus;
        }
        /// <summary>
        /// Web客户端使用，直接将订单创建到activityTemp表中
        /// </summary>
        /// <param name="createActivityModel"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<ActivityResultModel> CreateActivityTemp([FromBody]CreateActivityModel createActivityModel)
        {
            try
            {
                //判断提交数据的正确性
                var activity = this.IsGetActivityTemp(createActivityModel);
                //创建预留订单
                ActivityResultModel activityResultModel = await _activityTempManager.CreateActivity(activity);
                return activityResultModel;
            }
            catch (Exception ex)
            {
                return new ActivityResultModel()
                {
                    ResultCode = "001",
                    ResultMessage = ex.Message,
                    Detail = ex.StackTrace,
                };
            }
        }
        /// <summary>
        /// 提交预留订单
        /// </summary>
        /// <param name="ActivityTempId"></param>
        /// <returns></returns>
        [HttpPost]
        public ActivityResultModel CommitActivityTemp(Guid ActivityTempId)
        {
            try
            {
                //查询预留订单
                var activityTemp = _activityTempManager.GetActivityTempById(ActivityTempId);
                //填充订单信息
                var activity = FillActivityByTemp(activityTemp);
                //创建订单
                ActivityResultModel activityResultModel = _activityManager.CreateActivity(activity,activityTemp);
                _capBus.PublishAsync("swei.activity.create", activityResultModel.ActivityId);
                return activityResultModel;
            }
            catch (Exception ex)
            {
                return new ActivityResultModel()
                {
                    ResultCode = "001",
                    ResultMessage = ex.Message,
                    Detail = ex.StackTrace,
                };
            }
        }
        /// <summary>
        /// 取消暂存订单
        /// </summary>
        /// <param name="ActivityTempId"></param>
        /// <returns></returns>
        [HttpPost]
        public ActivityResultModel CancelActivityTemp(Guid ActivityTempId)
        {
            try
            {
                //查询预留订单
                var activityTemp = _activityTempManager.GetActivityTempById(ActivityTempId);
                //取消预留订单
                ActivityResultModel activityResultModel = _activityTempManager.CancelActivity(activityTemp,(long)AbpSession.UserId);
                //更新缓存中的航班剩余数
                foreach(var activityDetail in activityTemp.ActivityDetails)
                {
                    var schedule = GetSchedule((Guid)activityDetail.ScheduleId);
                    var ticketPrice = GetTicketPriceByCache(activityDetail.TicketPriceId);
                    IsExistenTicket(schedule, -activityDetail.Quantity, ticketPrice.WarePosition);
                }
                return activityResultModel;
            }
            catch (Exception ex)
            {
                return new ActivityResultModel()
                {
                    ResultCode = "001",
                    ResultMessage = ex.Message,
                    Detail = ex.StackTrace,
                };
            }
        }
        /// <summary>
        /// 旅行社扣除预留金创建订单
        /// </summary>
        /// <param name="createActivityModel"></param>
        /// <returns></returns>
        [HttpGet,HttpPost]
        public async Task<ActivityResultModel> CreateTravelActivity([FromBody]CreateActivityModel createActivityModel)
        {
            //判断登录用户是否是微信或官网用户
            if (StaticRoleNames.Host.Web != GetCurrentUser().UserName)
            {
                throw new Exception("当前登录账户不能调用该方法");
            }
            //设置售票源为官网
            var source = GetSourceList().FirstOrDefault(m => m.SourceCode == StaticRoleNames.Host.Web);
            createActivityModel.SourceId = source.Id;
            //设置支付方式为现金
            var payMethod = GetPayMethodList().FirstOrDefault(m => m.PayCode == "Cash");
            createActivityModel.PayMethodId = payMethod.Id;
            if (createActivityModel.TravelAgencyId == null)
                throw new Exception("不是旅行社订单");
            try
            {
                //判断提交数据的正确性
                var _activityTemp = this.IsGetActivityTemp(createActivityModel);
                //判断预存金额是否足够支付
                var travel = await _travelManager.GetEntityById((Guid)createActivityModel.TravelAgencyId);
                if(travel==null)
                {
                    throw new Exception("未找到该旅行社");
                }
                if (travel.PrepaidAmount < _activityTemp.TotalAmount)
                {
                    throw new Exception("预存金额不足，请充值或切换支付方式");
                }
                var groups = createActivityModel.activityDetails.GroupBy(m => m.ScheduleId);
                foreach (var item in groups)
                {
                    var count = await _ticketDetailManager.GetCountByTravel(travel.Id, item.Key);
                    if (count + item.Count() > travel.UpperLimit)
                    {
                        throw new Exception("购票数大于购票上限");
                    }
                }
                //if(_activityTemp.ActivityDetails.Count<travel.Lowerlimit)
                //{
                //    throw new Exception("购票数小于购票下限");
                //}
                //if (_activityTemp.ActivityDetails.Count > travel.UpperLimit)
                //{
                //    throw new Exception("购票数小于购票下限");
                //}
                //创建预留订单
                ActivityResultModel activityResultModel = await _activityTempManager.CreateActivity(_activityTemp);
                await CurrentUnitOfWork.SaveChangesAsync();
                //创建订单
                #region
                var activityTemp = (ActivityTemp)activityResultModel.Date;
                var activity = FillActivityByTemp(activityTemp); 
                #endregion
                activityResultModel = _activityManager.CreateActivity(activity, activityTemp);
                //扣除预存金额
                travel.PrepaidAmount -= activityTemp.TotalAmount;
                await _travelManager.SaveEntity(travel);
                //
                TravelConsumerMessage travelMessage = new TravelConsumerMessage()
                {
                    ActivityId = activityResultModel.ActivityId,
                    PayMethod = PayMethodEnum.PayFalse,
                };
                await _capBus.PublishAsync("swei.travel.activity.create", JsonConvert.SerializeObject(travelMessage));
                return activityResultModel;
            }
            catch (Exception ex)
            {
                return new ActivityResultModel()
                {
                    ResultCode = "001",
                    ResultMessage = ex.Message,
                    Detail = ex.StackTrace,
                };
            }
        }
        #region 私有方法
        #endregion
    }
}
